﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;

using SharedGenomics.Core;
using SharedGenomics.Workbench.Core;
using SharedGenomics.Workbench.Services;

namespace SharedGenomics.Workbench.Annotations.Requests
{
    public class TavernaClient : ITavernaClient
    {
        private readonly IAnnotationService _annotationService; //annotation service proxy
        private readonly HashSet<int> _idsInProgressSet;        //entrez gene ids being requested
        private const int SLOT_COUNT = 5;                       //max concurrent requests

        public TavernaClient(IAnnotationService annotationService)
        {
            this._annotationService = annotationService;
            this._idsInProgressSet = new HashSet<int>();
        }

        public IEnumerable<TavernaAnnotationData> ExecuteRequest(Func<int, IEnumerable<int>> idGenerator)
        {
            int availableSlots = SLOT_COUNT - this._idsInProgressSet.Count;
            Debug.Assert(availableSlots >= 0);

            //take as many items from the generator function as there are free slots and add them to the set of in progress ids
            this._idsInProgressSet.UnionWith(idGenerator(availableSlots));

            List<TavernaAnnotationData> completedAnnotations = null;
            this._annotationService.GetTavernaDataFor(this._idsInProgressSet).BindAction(data =>
            {
                completedAnnotations = data.CompletedRequests
                    .Select(rd => new TavernaAnnotationData(rd.EntrezGeneIdk__BackingField) { 
                        Gene = rd.Datak__BackingField.Genek__BackingField,
                        KeggPathways = rd.Datak__BackingField.KeggPathwaysk__BackingField,
                        Publications= rd.Datak__BackingField.Publicationsk__BackingField })
                    .ToList();

                //remove completed ids from the set of in-progress ids
                this._idsInProgressSet.ExceptWith(completedAnnotations.Select(a => a.EntrezGeneId));
            });

            return completedAnnotations ?? new List<TavernaAnnotationData>();
        }
    }
}
